home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / dnsresolv.inc < prev    next >
Encoding:
Text File  |  2004-12-28  |  7.6 KB  |  379 lines

  1. ; -*- fundamental -*-
  2. ; -----------------------------------------------------------------------
  3. ;   
  4. ;   Copyright 2004 H. Peter Anvin - All Rights Reserved
  5. ;
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  9. ;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  10. ;   (at your option) any later version; incorporated herein by reference.
  11. ;
  12. ; -----------------------------------------------------------------------
  13.  
  14. ;
  15. ; dnsresolv.inc
  16. ;
  17. ; Very simple DNS resolver (assumes recursion-enabled DNS server;
  18. ; this should be the normal thing for client-serving DNS servers.)
  19. ;
  20.  
  21. DNS_PORT    equ htons(53)        ; Default DNS port 
  22. DNS_MAX_PACKET    equ 512            ; Defined by protocol
  23. ; TFTP uses the range 49152-57343
  24. DNS_LOCAL_PORT    equ htons(60053)    ; All local DNS queries come from this port #
  25. DNS_MAX_SERVERS equ 4            ; Max no of DNS servers
  26.  
  27.         section .text
  28.  
  29. ;
  30. ; Turn a string in DS:SI into a DNS "label set" in ES:DI.
  31. ; On return, DI points to the first byte after the label set,
  32. ; and SI to the terminating byte.
  33. ;
  34. ; On return, DX contains the number of dots encountered.
  35. ;
  36. dns_mangle:
  37.         push ax
  38.         push bx
  39.         xor dx,dx
  40. .isdot:
  41.         inc dx
  42.         xor al,al
  43.         mov bx,di
  44.         stosb
  45. .getbyte:
  46.         lodsb
  47.         and al,al
  48.         jz .endstring
  49.         cmp al,':'
  50.         jz .endstring
  51.         cmp al,'.'
  52.         je .isdot
  53.         inc byte [es:bx]
  54.         stosb
  55.         jmp .getbyte
  56. .endstring:
  57.         dec si
  58.         dec dx            ; We always counted one high
  59.         cmp byte [es:bx],0
  60.         jz .done
  61.         xor al,al
  62.         stosb
  63. .done:
  64.         pop bx
  65.         pop ax
  66.         ret
  67.  
  68. ;
  69. ; Compare two sets of DNS labels, in DS:SI and ES:DI; the one in SI
  70. ; is allowed pointers relative to a packet in DNSRecvBuf.
  71. ;
  72. ; Assumes DS == ES.  ZF = 1 if same; no registers changed.
  73. ; (Note: change reference to [di] to [es:di] to remove DS == ES assumption)
  74. ;
  75. dns_compare:
  76.         pusha
  77. %if 0
  78.  
  79. .label:
  80.         lodsb
  81.         cmp al,0C0h
  82.         jb .noptr
  83.         and al,03Fh            ; Get pointer value
  84.         mov ah,al            ; ... in network byte order!
  85.         lodsb
  86.         mov si,DNSRecvBuf
  87.         add si,ax
  88.         jmp .label
  89. .noptr:
  90.         cmp al,[di]
  91.         jne .done            ; Mismatch
  92.         inc di
  93.         movzx cx,al            ; End label?
  94.         and cx,cx            ; ZF = 1 if match
  95.         jz .done
  96.         
  97.         ; We have a string of bytes that need to match now
  98.         repe cmpsb
  99.         je .label
  100.  
  101. .done:
  102. %else
  103.         xor ax,ax
  104. %endif
  105.         popa
  106.         ret
  107.  
  108. ;
  109. ; Skip past a DNS label set in DS:SI.
  110. ;
  111. dns_skiplabel:
  112.         push ax
  113.         xor ax,ax            ; AH == 0
  114. .loop:
  115.         lodsb
  116.         cmp al,0C0h            ; Pointer?
  117.         jae .ptr
  118.         and al,al
  119.         jz .done
  120.         add si,ax
  121.         jmp .loop
  122. .ptr:
  123.         inc si                ; Pointer is two bytes
  124. .done:
  125.         pop ax
  126.         ret
  127.  
  128.         ; DNS header format
  129.         struc dnshdr
  130. .id:        resw 1
  131. .flags:        resw 1
  132. .qdcount:    resw 1
  133. .ancount:    resw 1
  134. .nscount:    resw 1
  135. .arcount:    resw 1
  136.         endstruc
  137.  
  138.         ; DNS query
  139.         struc dnsquery
  140. .qtype:        resw 1
  141. .qclass:    resw 1
  142.         endstruc
  143.  
  144.         ; DNS RR
  145.         struc dnsrr
  146. .type:        resw 1
  147. .class:        resw 1
  148. .ttl:        resd 1
  149. .rdlength:    resw 1
  150. .rdata:        equ $
  151.         endstruc
  152.  
  153.         section .bss
  154.         alignb 2, db 0
  155. DNSSendBuf    resb DNS_MAX_PACKET
  156. DNSRecvBuf    resb DNS_MAX_PACKET
  157. LocalDomain    resb 256        ; Max possible length
  158. DNSServers    resd DNS_MAX_SERVERS
  159.  
  160.         section .data
  161. pxe_udp_write_pkt_dns:
  162. .status:    dw 0            ; Status
  163. .sip:        dd 0            ; Server IP
  164. .gip:        dd 0            ; Gateway IP
  165. .lport:        dw DNS_LOCAL_PORT    ; Local port
  166. .rport:        dw DNS_PORT        ; Remote port
  167. .buffersize:    dw 0            ; Size of packet
  168. .buffer:    dw DNSSendBuf, 0    ; off, seg of buffer
  169.  
  170. pxe_udp_read_pkt_dns:
  171. .status:    dw 0            ; Status
  172. .sip:        dd 0            ; Source IP
  173. .dip:        dd 0            ; Destination (our) IP
  174. .rport:        dw DNS_PORT        ; Remote port
  175. .lport:        dw DNS_LOCAL_PORT    ; Local port
  176. .buffersize:    dw DNS_MAX_PACKET    ; Max packet size
  177. .buffer:    dw DNSRecvBuf, 0    ; off, seg of buffer
  178.  
  179. LastDNSServer    dw DNSServers
  180.  
  181. ; Actual resolver function
  182. ; Points to a null-terminated or :-terminated string in DS:SI
  183. ; and returns the name in EAX if it exists and can be found.
  184. ; If EAX = 0 on exit, the lookup failed.
  185.  
  186.         section .text
  187. dns_resolv:
  188.         push ds
  189.         push es
  190.         push di
  191.         push cx
  192.         push dx
  193.  
  194.         push cs
  195.         pop es            ; ES <- CS
  196.  
  197.         ; First, build query packet
  198.         mov di,DNSSendBuf+dnshdr.flags
  199.         inc word [es:di-2]    ; New query ID
  200.         mov ax,htons(0100h)    ; Recursion requested
  201.         stosw
  202.         mov ax,htons(1)        ; One question
  203.         stosw
  204.         xor ax,ax        ; No answers, NS or ARs
  205.         stosw
  206.         stosw
  207.         stosw
  208.         
  209.         call dns_mangle        ; Convert name to DNS labels
  210.  
  211.         push cs            ; DS <- CS
  212.         pop ds
  213.  
  214.         push si            ; Save pointer to after DNS string
  215.  
  216.         ; Initialize...
  217.         mov eax,[MyIP]
  218.         mov [pxe_udp_read_pkt_dns.dip],eax
  219.  
  220.         and dx,dx
  221.         jnz .fqdn        ; If we have dots, assume it's FQDN
  222.         dec di            ; Remove final null
  223.         mov si,LocalDomain
  224.         call strcpy        ; Uncompressed DNS label set so it ends in null
  225. .fqdn:
  226.  
  227.         mov ax,htons(1)
  228.         stosw            ; QTYPE  = 1 = A
  229.         stosw            ; QCLASS = 1 = IN
  230.  
  231.         sub di,DNSSendBuf
  232.         mov [pxe_udp_write_pkt_dns.buffersize],di
  233.  
  234.         ; Now, send it to the nameserver(s)
  235.         ; Outer loop: exponential backoff
  236.         ; Inner loop: scan the various DNS servers
  237.  
  238.         mov dx,PKT_TIMEOUT
  239.         mov cx,PKT_RETRY
  240. .backoff:
  241.         mov si,DNSServers
  242. .servers:
  243.         cmp si,[LastDNSServer]
  244.         jb .moreservers
  245.  
  246. .nomoreservers:
  247.         add dx,dx            ; Exponential backoff
  248.         loop .backoff
  249.  
  250.         xor eax,eax            ; Nothing...
  251. .done:
  252.         pop si
  253.         pop dx
  254.         pop cx
  255.         pop di
  256.         pop es
  257.         pop ds
  258.         ret
  259.  
  260. .moreservers:
  261.         lodsd                ; EAX <- next server
  262.         push si
  263.         push cx
  264.         push dx
  265.  
  266.         mov word [pxe_udp_write_pkt_dns.status],0    
  267.  
  268.         mov [pxe_udp_write_pkt_dns.sip],eax
  269.         mov [pxe_udp_read_pkt_dns.sip],eax
  270.         xor eax,[MyIP]
  271.         and eax,[Netmask]
  272.         jz .nogw
  273.         mov eax,[Gateway]
  274. .nogw:
  275.         mov [pxe_udp_write_pkt_dns.gip],eax
  276.  
  277.         mov di,pxe_udp_write_pkt_dns
  278.         mov bx,PXENV_UDP_WRITE
  279.         call pxenv
  280.         jc .timeout                ; Treat failed transmit as timeout
  281.         cmp word [pxe_udp_write_pkt_dns.status],0
  282.         jne .timeout
  283.  
  284.         mov cx,[BIOS_timer]
  285. .waitrecv:
  286.         mov ax,[BIOS_timer]
  287.         sub ax,cx
  288.         cmp ax,dx
  289.         jae .timeout
  290.  
  291.         mov word [pxe_udp_read_pkt_dns.status],0
  292.         mov word [pxe_udp_read_pkt_dns.buffersize],DNS_MAX_PACKET
  293.         mov di,pxe_udp_read_pkt_dns
  294.         mov bx,PXENV_UDP_READ
  295.         call pxenv
  296.         and ax,ax
  297.         jnz .waitrecv
  298.         cmp [pxe_udp_read_pkt_dns.status],ax
  299.         jnz .waitrecv
  300.  
  301.         ; Got a packet, deal with it...
  302.         mov si,DNSRecvBuf
  303.         lodsw
  304.         cmp ax,[DNSSendBuf]        ; ID
  305.         jne .waitrecv            ; Not ours
  306.  
  307.         lodsw                ; flags
  308.         xor al,80h            ; Query#/Answer bit
  309.         test ax,htons(0F80Fh)
  310.         jnz .badness
  311.         
  312.         lodsw
  313.         xchg ah,al            ; ntohs
  314.         mov cx,ax            ; Questions echoed
  315.         lodsw
  316.         xchg ah,al            ; ntohs
  317.         push ax                ; Replies
  318.         lodsw                ; NS records
  319.         lodsw                ; Authority records
  320.  
  321.         jcxz .qskipped
  322. .skipq:
  323.         call dns_skiplabel        ; Skip name
  324.         add si,4            ; Skip question trailer
  325.         loop .skipq
  326.  
  327. .qskipped:
  328.         pop cx                ; Number of replies
  329.         jcxz .badness
  330.  
  331. .parseanswer:
  332.         mov di,DNSSendBuf+dnshdr_size
  333.         call dns_compare
  334.         pushf
  335.         call dns_skiplabel
  336.         mov ax,[si+8]            ; RDLENGTH
  337.         xchg ah,al            ; ntohs
  338.         popf
  339.         jnz .notsame
  340.         cmp dword [si],htons(1)*0x10001    ; TYPE = A, CLASS = IN?
  341.         jne .notsame
  342.         cmp ax,4            ; RDLENGTH = 4?
  343.         jne .notsame
  344.         ;
  345.         ; We hit paydirt here...
  346.         ;
  347.         mov eax,[si+10]
  348. .gotresult:
  349.         add sp,6            ; Drop timeout information
  350.         jmp .done
  351.  
  352. .notsame:
  353.         add si,10
  354.         add si,ax
  355.         loop .parseanswer
  356.  
  357. .badness:
  358.         ; We got back no data from this server.  Unfortunately, for a recursive,
  359.         ; non-authoritative query there is no such thing as an NXDOMAIN reply,
  360.         ; which technically means we can't draw any conclusions.  However,
  361.         ; in practice that means the domain doesn't exist.  If this turns out
  362.         ; to be a problem, we may want to add code to go through all the servers
  363.         ; before giving up.
  364.  
  365.         ; If the DNS server wasn't capable of recursion, and isn't capable
  366.         ; of giving us an authoritative reply (i.e. neither AA or RA set),
  367.         ; then at least try a different setver...
  368.         test word [DNSRecvBuf+dnshdr.flags],htons(0480h)
  369.         jz .timeout
  370.         
  371.         xor eax,eax
  372.         jmp .gotresult
  373.  
  374. .timeout:
  375.         pop dx
  376.         pop cx
  377.         pop si
  378.         jmp .servers
  379.